(function($){
	
	var settings = { //defaults
			errorclass:'fcheck-error',
			containerclass:'fcheck-error-container',
			strings:{
					en:{
					empty:"field %s is mandatory",
					email:"field %s is not a valid address",
					numeric:"field %s must be numeric",
					alpha:"field %s must be alphabetic",
					alphanum:"field %s can contain letters and numbers only",
					codfisc:"field %s is not a valid fiscal code",
					piva:"field %s is not a valid VAT code",
					alphaspace:"field %s can contain only letters and spaces",
					fileformat:"file %s is not a valid format",
					numspace:"field %s can contain only numbers and spaces",
					errors:"Errors:"
				}
			},
			lang:'en',
			callback:function(res){
				return res;
			}
	};
	
	var errors=[]; //global var for errors
	
	var methods= {
		init:function(th,fields,options){ //init function checks for requested checks and performs them
			$(th).bind('submit',function(){
				$.extend(settings,options);
				
				// reset from previous checks
				errors=[];
				$("."+settings.containerclass).remove();
				$("."+settings.errorclass).removeClass(settings.errorclass);
				
				//main section
				for (var i in fields){
					if(fields[i].empty===true) methods.isempty(th,fields[i].selector,i);
					if(fields[i].numeric===true) methods.isnumeric(th,fields[i].selector,i);
					if(fields[i].email==true) methods.isemail(th,fields[i].selector,i);
					if(fields[i].piva===true) methods.ispiva(th,fields[i].selector,i);
					if(fields[i].codfisc===true) methods.iscodfisc(th,fields[i].selector,i);
					if(fields[i].alpha===true) methods.isalpha(th,fields[i].selector,i);
					if(fields[i].alphanum===true) methods.isalphanum(th,fields[i].selector,i);
					if(fields[i].alphspace===true) methods.isalphaspace(th,fields[i].selector,i);
					if(fields[i].fileformat===true) methods.fileformat(th,fields[i].selector,i,fields[i].formats);
					if(fields[i].numspace===true) methods.numspace(th,fields[i].selector,i);
				}
				
				//after all checks are performed write errors
				return methods.writeerrors(th);
			});
		},
		
		//checks
		isempty:function(th,selector,label){ //empty field check
			if($(selector).val()==''){
				methods.showerror(th,selector,'empty',label);
			}
		},
		
		isemail:function(th,selector,label){ //email check
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				mailreg=/^([a-z0-9]+)([a-z0-9.\-_]*)([@].)([a-z0-9.\-_]*)([.].)([a-z]{1,2})$/;
				value=$(selector).val();
				if(mailreg.test(value)==false){
					methods.showerror(th,selector,'email',label);
				}
			}
		},
		
		isnumeric:function(th,selector,label){ //numeric field check
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				numreg=/[^0-9]/;
				value=$(selector).val();
				if(numreg.test(value)==true){
					methods.showerror(th,selector,'numeric',label);
				}	
			}
		},
		
		ispiva:function(th,selector,label){ //partita iva (VAT) check, (11 numbers)
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				numreg=/[^0-9]/;
				value=$(selector).val();
				if(value.length!=11 || numreg.test(value)==true){
					methods.showerror(th,selector,'piva',label);
				}
			}
		},
		
		iscodfisc:function(th,selector,label){ //codice fiscale
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				fiscreg=/^([a-zA-Z]{6})+([0-9]{2})+([a-zA-Z]{1})+([0-9]{2})+([a-zA-Z]{1})+([0-9]{3})+([a-zA-Z]{1})$/;
				value=$(selector).val();
				if(value.length!=16 || fiscreg.test(value)==false){
					methods.showerror(th,selector,'codfisc',label);
				}
			}
		},
		
		isalpha:function(th,selector,label){ //only letters field
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				alphareg=/[^a-zA-Z]/;
				value=$(selector).val();
				if(alphareg.test(value)==true){
					methods.showerror(th,selector,'alpha',label);
				}
			}
		},
		
		isalphanum:function(th,selector,label){ //only letters and numbers
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				alnumreg=/[^0-9a-zA-Z]/;
				value=$(selector).val();
				if(alnumreg.test(value)==true){
					methods.showerror(th,selector,'alphanum',label);
				}
			}
		},
		isalphaspace:function(th,selector,label){
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				alspreg=/[^a-zA-Z\ ]/;
				value=$(selector).val();
				if(alspreg.test(value)==true){
					methods.showerror(th,selector,'alphaspace',label);
				}
			}
		},
		fileformat:function(th,selector,label,formats){
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				value=$(selector).val();
				dot=value.lastIndexOf('.');
				ext=value.substr(dot);
				ext=ext.toLowerCase();
				var err=true;
				for(i in formats){
					if(formats[i]==ext) err=false;
				}
				if(err==true){
					methods.showerror(th,selector,'fileformat',label);
				}
			}
		},
		numspace:function(th,selector,label){
			if($(selector).val()!='' && typeof($(selector).val())!='undefined'){
				alspreg=/[^0-9\ ]/;
				value=$(selector).val();
				if(alspreg.test(value)==true){
					methods.showerror(th,selector,'numspace',label);
				}
			}
		},
		//end checks
		
		showerror:function(th,selector,error,label){ //adds an error to errors global variable and changes input class
			errorstring=methods.translate(error,label);
			errors.push(errorstring);
			$(selector).addClass(settings.errorclass);
		},
		
		writeerrors:function(th){ //final function, create a div containing the error messages and authorize or not form submission
			if(errors.length>0){
				var string=settings.strings[settings.lang].errors;
				$(th).before('<div class="'+settings.containerclass+'"><span>'+string+'</span><ul></ul></div>');
				for(var x in errors){
					$("."+settings.containerclass+" ul").append('<li>'+errors[x]+'</li>');
				}
				res=false;
			}
			else {
				res=true;
			}
			return settings.callback(res);
		},
		
		translate:function(string,label){ //function for string localization
			reg=/%s/;
			return settings.strings[settings.lang][string].replace(reg,label);
		}
	};
	
	//main plugin section
	jQuery.fn.formCheck = function(options){
		
		if(options.method=="translation"){
			$.extend(settings.strings,options.strings);
			return false;
		}
		
		return this.each(function(){
			
			var th = $(this);
			
			var fields=options.fields; 
			
			if(options){
				
				methods.init(th,fields,options);
			}
		});
	};
})(jQuery);